package com.market.plus.controller.mapper;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;

import com.market.plus.core.dto.AvatarDto;
import com.market.plus.core.dto.CommentDto;
import com.market.plus.core.dto.ContentFileDto;
import com.market.plus.core.dto.NewsDto;
import com.market.plus.core.dto.ParticipantDto;
import com.market.plus.core.dto.RelationshipDto;
import com.market.plus.core.dto.TribeDto;

@Component("jsonMapping")
public class JsonMappingImpl implements JsonMapping {

   static final String[] PARTICIPANT_PROPERTIES_HIDDEN=new String[]{"city","address","zipcode","userInfo","status"};

   static final String[] NEWS_PROPERTIES_HIDDEN=new String[]{"title","newsType","createdUser","createdDate","modifyedUser","modifyedDate"};

   static final String[] TRIBE_PROPERTIES_HIDDEN=new String[]{"id","description","avatar"};

   static final String[] NEWS_ALLPROPERTIES_HIDDEN;
   
   static final String[] COMMENTS_ALLPROPERTIES_HIDDEN;

   static final String[] TRIBE_ALLPROPERTIES_HIDDEN;

   @Autowired
   private ResourceBundleMessageSource messageSource;

   public JSONObject convert(ParticipantDto participantDto, NewsDto introduction, boolean isGuest) {
      JSONObject participantObject = new JSONObject();
      participantObject.put("id", participantDto.getId());
      String firstName = participantDto.getFirstName();
      String lastName = participantDto.getLastName();
      participantObject.put("firstName", firstName);
      participantObject.put("lastName", lastName);
      String nickName = participantDto.getNickname(); 
      if (nickName == null || nickName.trim().length() == 0){
         char[] cFirstName = firstName.toCharArray();
         cFirstName[0] = Character.toUpperCase(cFirstName[0]);
         nickName = String.valueOf(cFirstName);
         char[] cLastName = lastName.toCharArray();
         cLastName[0] = Character.toUpperCase(cLastName[0]);
         nickName = String.valueOf(cFirstName)  + " " + String.valueOf(cLastName);
      }
      participantObject.put("nickname", nickName);
      participantObject.put("guid", participantDto.getGuid());
      participantObject.put("isGuest",isGuest);
      AvatarDto avatarDto = participantDto.getAvatar();
      participantObject.put("avatarGUID", avatarDto != null ? avatarDto.getContentFile().getGuid() : "0");
      participantObject.put("introduction", convertJSON(introduction));
      return participantObject;
   }

   private JSONObject convertJSON(NewsDto introduction){
      String content = "";
      long id=0;
      JSONObject introdutionObject = new JSONObject();
      if (introduction != null && introduction.getContent() != null){
         content = introduction.getContent();
         id = introduction.getId();
         introdutionObject.put("content", content);
         introdutionObject.put("id", id);
         List<ContentFileDto> contentFiles = introduction.getContentFiles();
         JSONArray fileArray = new JSONArray();
         if (contentFiles != null && contentFiles.size() > 0){
            for (ContentFileDto contentFileDto : contentFiles){
               JSONObject fileObject = new JSONObject();
               fileObject.put("guid", contentFileDto.getGuid());
               fileArray.add(fileObject);
            }
         }
         introdutionObject.put("files", fileArray);
      }
      return introdutionObject;
   }

   public JSONObject convertFirtsTribeNews(TribeDto tribeDto) {
      JsonConfig jsonConfig = new JsonConfig();
      String[] propertiesName=TRIBE_ALLPROPERTIES_HIDDEN;
      CustomPropertyFilter customPropertyFilter = new CustomPropertyFilter();
      customPropertyFilter.setExcludeProperties(propertiesName);
      jsonConfig.setJsonPropertyFilter(customPropertyFilter);
      JSONObject jsonObject = JSONObject.fromObject(tribeDto,jsonConfig);
      jsonObject.put("btnlabel", messageSource.getMessage("tribe.menu.add.news", null, null));
      return jsonObject;
   }

   public JSONArray convertNews(List<NewsDto> newsDtos) {
      JsonConfig jsonConfig = new JsonConfig();
      String[] propertiesName=NEWS_ALLPROPERTIES_HIDDEN;
      CustomPropertyFilter customPropertyFilter = new CustomPropertyFilter();
      customPropertyFilter.setExcludeProperties(propertiesName);
      jsonConfig.setJsonPropertyFilter(customPropertyFilter);
      JSONArray jsonArray = new JSONArray();
      for (NewsDto newsDto:newsDtos){
         JSONObject jsonObject = JSONObject.fromObject(newsDto,jsonConfig);
         jsonArray.add(jsonArray.size(), jsonObject);
         customPropertyFilter.reset();
      }
      return jsonArray;
   }

   public JSONArray convertComments(List<CommentDto> comments) {
      JsonConfig jsonConfig = new JsonConfig();
      String[] propertiesName=COMMENTS_ALLPROPERTIES_HIDDEN;
      CustomPropertyFilter customPropertyFilter = new CustomPropertyFilter();
      customPropertyFilter.setExcludeProperties(propertiesName);
      jsonConfig.setJsonPropertyFilter(customPropertyFilter);
      JSONArray jsonArray = new JSONArray();
      for (CommentDto commentDto:comments){
         JSONObject jsonObject = JSONObject.fromObject(commentDto,jsonConfig);
         jsonArray.add(jsonArray.size(), jsonObject);
         customPropertyFilter.reset();
      }
      return jsonArray;
   }

   public JSONObject convertRelationship(List<ParticipantDto> participants, List<RelationshipDto> relationships){
      JsonConfig jsonConfig = new JsonConfig();
      CustomPropertyFilter customPropertyFilter = new CustomPropertyFilter();
      jsonConfig.setJsonPropertyFilter(customPropertyFilter);

      String[] excludePropertiesName=new String[]{"city","address","zipcode","userInfo","status"};
      customPropertyFilter.setExcludeProperties(excludePropertiesName);

      JSONObject relationshipObject = new JSONObject();
      JSONArray friendJsonArray = new JSONArray();
      for (ParticipantDto participantDto:participants){
         JSONObject participantObject = JSONObject.fromObject(participantDto,jsonConfig);
         friendJsonArray.add(friendJsonArray.size(), participantObject);
         customPropertyFilter.reset();
      }

      excludePropertiesName=new String[]{"friends.hasAccepted","friends.acceptedDate","friends.lockStatus","friends.hasPrivated","friends.requestedDate",
            "friends.participant.city","friends.participant.address","friends.participant.zipcode","friends.participant.userInfo","friends.participant.status"};
      customPropertyFilter.setExcludeProperties(excludePropertiesName);
      JSONArray relationshipJsonArray = new JSONArray();
      for (RelationshipDto relationshipDto:relationships){
         JSONObject jsonObject = JSONObject.fromObject(relationshipDto,jsonConfig);
         relationshipJsonArray.add(relationshipJsonArray.size(), jsonObject);
         customPropertyFilter.reset();
      }
      relationshipObject.put("label1", messageSource.getMessage("relationship.add", null, null));
      relationshipObject.put("friends", friendJsonArray);
      relationshipObject.put("relationships", relationshipJsonArray);
      return relationshipObject;
   }

   static {
      List<String> properties = new ArrayList<String>();
      for(String str:PARTICIPANT_PROPERTIES_HIDDEN){
         properties.add("participant."+str);
         properties.add("comments.participant."+str);
      }
      properties.addAll(Arrays.asList(NEWS_PROPERTIES_HIDDEN));
      NEWS_ALLPROPERTIES_HIDDEN=properties.toArray(new String[]{});

      properties = new ArrayList<String>();
      for(String str:PARTICIPANT_PROPERTIES_HIDDEN){
         properties.add("news.participant."+str);
         properties.add("news.comments.participant."+str);
      }
      for(String str:NEWS_PROPERTIES_HIDDEN){
         properties.add("news."+str);
      }
      properties.addAll(Arrays.asList(TRIBE_PROPERTIES_HIDDEN));
      TRIBE_ALLPROPERTIES_HIDDEN=properties.toArray(new String[]{});
      
      properties = new ArrayList<String>();
      for(String str:PARTICIPANT_PROPERTIES_HIDDEN){
         properties.add("participant."+str);
      }
      COMMENTS_ALLPROPERTIES_HIDDEN=properties.toArray(new String[]{});
   }

   public JSONObject acceptFriendStatus() {
      JSONObject jsonObject = new JSONObject();
      jsonObject.put("messageSucc", messageSource.getMessage("friend.succ.message.accept", null, null));
      return jsonObject;
   }

   public JSONObject requestFriendStatus() {
      JSONObject jsonObject = new JSONObject();
      jsonObject.put("messageSucc", messageSource.getMessage("friend.succ.message.request", null, null));
      return jsonObject;
   }

   public JSONObject denyFriendStatus() {
      JSONObject jsonObject = new JSONObject();
      jsonObject.put("messageSucc", messageSource.getMessage("friend.succ.message.deny", null, null));
      return jsonObject;
   }
   
   public JSONObject lockedFriendStatus() {
      JSONObject jsonObject = new JSONObject();
      jsonObject.put("messageSucc", messageSource.getMessage("friend.succ.message.lock", null, null));
      return jsonObject;
   }

   public JSONObject unlockedFriendStatus() {
      JSONObject jsonObject = new JSONObject();
      jsonObject.put("messageSucc", messageSource.getMessage("friend.succ.message.unlock", null, null));
      return jsonObject;
   }

   public JSONObject addFriendToRelationshipStatus() {
      JSONObject jsonObject = new JSONObject();
      jsonObject.put("messageSucc", messageSource.getMessage("relationship.succ.message.friend.add", null, null));
      return jsonObject;
   }

   public JSONObject removeFriendFromRelationshipStatus() {
      JSONObject jsonObject = new JSONObject();
      jsonObject.put("messageSucc", messageSource.getMessage("relationship.succ.message.friend.remove", null, null));
      return jsonObject;
   }
   
   public JSONObject removeRelationshipStatus() {
      JSONObject jsonObject = new JSONObject();
      jsonObject.put("messageSucc", messageSource.getMessage("relationship.succ.message.remove", null, null));
      return jsonObject;
   }

   public JSONObject saveNewsStatus(String guid) {
      JSONObject jsonObject = new JSONObject();
      jsonObject.put("messageSucc", messageSource.getMessage("news.succ.message.post", null, null));
      jsonObject.put("guid", guid);
      return jsonObject;
   }

   public JSONObject addRelationshipStatus(RelationshipDto relationship, BindingResult result) {
      JSONObject jsonObject = new JSONObject();
      if (result.hasErrors()){
         jsonObject.put("hasError",true);
         List<FieldError> fieldErrors = result.getFieldErrors();
         JSONArray jsonArray = new JSONArray();
         for (FieldError fieldError : fieldErrors){
            JSONObject fieldJson = new JSONObject();
            fieldJson.put("name", fieldError.getField());
            fieldJson.put("value", messageSource.getMessage(fieldError.getCode(), null, null));
            jsonArray.add(fieldJson);
         }
         jsonObject.put("fields",jsonArray);
      }else{
         jsonObject.put("messageSucc",messageSource.getMessage("relationship.succ.message.add", null, null));
         jsonObject.put("id",relationship.getId());
         jsonObject.put("relationName",relationship.getRelationName());
      }
      return jsonObject;
   }
}
